package com.rxtxdemo.rxtxdemo.core;

import com.rxtxdemo.rxtxdemo.service.ISerialPortService;
import gnu.io.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/*
 *
 * @author  潘林林
 * @date  2018/5/28 15:11
 *
 */
@Component
public class SerialPortCore {
    private int timeout = 2000;//open 端口时的等待时间

    @Value("${baudRate}")
    private int baudRate;
    @Value("${dataBits}")
    private int dataBits;
    @Value("${stopBits}")
    private int stopBits;
    @Value("${parity}")
    private int parity; // 0 表示none

    private SerialPort serialPort ;

    @Autowired
    public ISerialPortService serialPortService;


    /**
     * @方法名称 :listPort
     * @功能描述 :列出所有可用的串口
     * @返回值类型 :void
     */
    @SuppressWarnings("rawtypes")
    public List<CommPortIdentifier> listPort(){
        List<CommPortIdentifier> cpidList = new ArrayList<>();
        Enumeration en = CommPortIdentifier.getPortIdentifiers();

        System.out.println("now to list all Port of this PC：" +en);

        while(en.hasMoreElements()){
            CommPortIdentifier cpid = (CommPortIdentifier)en.nextElement();
            if(cpid.getPortType() == CommPortIdentifier.PORT_SERIAL){
                cpidList.add(cpid);
            }
        }
        return cpidList;
    }

    public void connect (String portName) throws Exception {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        if ( portIdentifier.isCurrentlyOwned() ) {
            System.out.println("Error: Port is currently in use");
        } else {
            CommPort commPort = portIdentifier.open(this.getClass().getName(),timeout);
            if ( commPort instanceof SerialPort) {
                serialPort = (SerialPort) commPort;
                // 参数
                serialPort.setSerialPortParams(baudRate,dataBits,stopBits,parity);

                InputStream in = serialPort.getInputStream();

                serialPort.addEventListener(new SerialReader(in));
                serialPort.notifyOnDataAvailable(true);

                System.out.println("连接 " + portName + " 成功");
            } else {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }
    }

    public class SerialReader implements SerialPortEventListener {
        private InputStream in;
        private byte[] buffer = new byte[1024];

        public SerialReader ( InputStream in ) {
            this.in = in;
        }

        public void serialEvent(SerialPortEvent arg0) {
            int data;
            try {
                int len = 0;
                while ( ( data = in.read()) > -1 ) {
                    if ( data == '\n' ) {
                        break;
                    }
                    buffer[len++] = (byte) data;
                }
                serialPortService.serialPortMsgHandler(new String(buffer,0,len));
            } catch ( IOException e ) {
                e.printStackTrace();
                System.exit(-1);
            }
        }
    }

    /** */
    public class SerialWriter implements Runnable {
        OutputStream out;
        public SerialWriter (OutputStream out) {
            this.out = out;
        }

        public void run () {
            try {
                int c = 0;
                while ( ( c = System.in.read()) > -1 ) {
                    this.out.write(c);
                }
            } catch ( IOException e ) {
                e.printStackTrace();
            }
        }
    }
    public void sendMsg(String msg) {
        if (!StringUtils.isEmpty(msg)) {
            try {
                OutputStream out = serialPort.getOutputStream();
                out.write(msg.getBytes());
                (new Thread(new SerialPortCore.SerialWriter(out))).start();
            }catch (IOException e) {
                System.out.println("消息发送失败");
                e.printStackTrace();
            }
        }
    }
}
